package com.ibeeking.found.msg.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ibeeking.found.common.config.feign.GlobalClient;
import com.ibeeking.found.common.entity.DictDTO;
import com.ibeeking.found.common.enums.DictTypeEnum;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.msg.rest.service.IMsgRecordService;
import com.ibeeking.found.msg.service.common.dos.MsgRecordAttachDO;
import com.ibeeking.found.msg.service.common.dos.MsgRecordDO;
import com.ibeeking.found.msg.service.common.enums.MsgReadStatusEnum;
import com.ibeeking.found.msg.service.common.enums.PriorityLevelEnum;
import com.ibeeking.found.msg.service.common.param.MsgRecordAttachParam;
import com.ibeeking.found.msg.service.common.param.MsgRecordParam;
import com.ibeeking.found.msg.service.common.query.MsgRecordPageQuery;
import com.ibeeking.found.msg.service.common.query.MsgRecordQuery;
import com.ibeeking.found.msg.service.common.vo.MsgRecordAttachVO;
import com.ibeeking.found.msg.service.common.vo.MsgRecordVO;
import com.ibeeking.found.msg.service.mapper.MsgRecordAttachMapper;
import com.ibeeking.found.msg.service.mapper.MsgRecordMapper;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.id.IdGenerator;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @ClassName MsgRecordServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-01-11 17:33
 **/
@Service
public class MsgRecordServiceImpl extends ServiceImpl<MsgRecordMapper, MsgRecordDO> implements IMsgRecordService {

    private static final DateTimeFormatter dateTimeformatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Resource
    private MsgRecordMapper msgRecordMapper;

    @Resource
    private MsgRecordAttachMapper msgRecordAttachMapper;

    @Resource
    private GlobalClient globalClient;

    @Override
    public List<MsgRecordVO> list(MsgRecordQuery query){
        List<MsgRecordDO> entityDOS = msgRecordMapper.selectList(new LambdaQueryWrapper<MsgRecordDO>()
                .eq(query.getId() != null, MsgRecordDO::getId, query.getId())
                .eq(query.getSenderId() != null, MsgRecordDO::getSenderId, query.getSenderId())
                .eq(StringUtils.isNotBlank(query.getTitle()), MsgRecordDO::getTitle, query.getTitle())
                .eq(query.getType() != null, MsgRecordDO::getType, query.getType())
                .eq(query.getPriorityLevel() != null, MsgRecordDO::getPriorityLevel, query.getPriorityLevel())
                .eq(query.getReadFlag() != null, MsgRecordDO::getReadFlag, query.getReadFlag())
                .ge(StringUtils.isNotBlank(query.getSendTimeStart()), MsgRecordDO::getSendTime, query.getSendTimeStart())
                .le(StringUtils.isNotBlank(query.getSendTimeEnd()), MsgRecordDO::getSendTime, query.getSendTimeEnd())
                .orderByDesc(MsgRecordDO::getSendTime,MsgRecordDO::getModifyTime)
        );
        List<MsgRecordVO> entityResultVOS = new ArrayList<MsgRecordVO>();
        if(Collections3.isNotEmpty(entityDOS)){
            List<DictDTO> WikiDictList = Optional.ofNullable(globalClient.queryDictByType(DictTypeEnum.WIKI_TYPE.getValue())).map(ResponseResult::getData).orElse(Collections3.emptyList());
            Map<String, String> WikiDictMap = WikiDictList.parallelStream().collect(Collectors.toMap(DictDTO::getValue, DictDTO::getLabel, (s, a) -> a));

            List<MsgRecordVO> entityVOS = JsonUtils.jsonToList(entityDOS, MsgRecordVO.class);
            entityResultVOS = entityVOS.stream().map(c->{
                MsgRecordVO entityVO = BeanUtil.convertBean(c, MsgRecordVO.class);
                List<MsgRecordAttachDO> entityAttachDOS = msgRecordAttachMapper.selectList(new LambdaQueryWrapper<MsgRecordAttachDO>()
                        .eq(MsgRecordAttachDO::getMsgId, c.getId())
                );
                if(Collections3.isNotEmpty(entityAttachDOS)) {
                    List<MsgRecordAttachVO> entityAttachVOS = JsonUtils.jsonToList(entityAttachDOS, MsgRecordAttachVO.class);
                    entityVO.setMsgAttachs(entityAttachVOS);
                }
                entityVO.setPriorityLevelName(PriorityLevelEnum.getNameByLevel(c.getPriorityLevel()));
                entityVO.setReadFlagName(MsgReadStatusEnum.getNameByValue(c.getReadFlag()));
                entityVO.setTypeName(WikiDictMap.get(c.getType().toString()));
                if(c.getSendTime() != null) {
                    entityVO.setSendTimeStr(dateTimeformatter.format(c.getSendTime()));
                }
                if(c.getCreateTime() != null) {
                    entityVO.setCreateTimeStr(dateTimeformatter.format(c.getCreateTime()));
                }
                return entityVO;
             }).collect(Collectors.toList());
        }

        return entityResultVOS;
    }

    @Override
    public List<MsgRecordVO> listEffectSimpleMsg(Integer rows){
        List<MsgRecordDO> entityDOS = msgRecordMapper.querySimpleMsg(rows);

        List<MsgRecordVO> entityResultVOS = new ArrayList<MsgRecordVO>();
        if(Collections3.isNotEmpty(entityDOS)){
            List<DictDTO> WikiDictList = Optional.ofNullable(globalClient.queryDictByType(DictTypeEnum.WIKI_TYPE.getValue())).map(ResponseResult::getData).orElse(Collections3.emptyList());
            Map<String, String> WikiDictMap = WikiDictList.parallelStream().collect(Collectors.toMap(DictDTO::getValue, DictDTO::getLabel, (s, a) -> a));

            entityResultVOS = entityDOS.stream().map(c->{
                MsgRecordVO MsgRecordVO = BeanUtil.convertBean(c, MsgRecordVO.class);
                String typeName = WikiDictMap.get(c.getType().toString());
                String newTitle = "【" + typeName + "】" + c.getTitle();
                MsgRecordVO.setTitle(newTitle);
                MsgRecordVO.setContent(null);
                return MsgRecordVO;
            }).collect(Collectors.toList());
        }

        return entityResultVOS;
    }

    @Override
    public Page<MsgRecordVO> pageList(MsgRecordPageQuery pageQuery){
        LambdaQueryWrapper<MsgRecordDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(pageQuery.getId() != null, MsgRecordDO::getId, pageQuery.getId())
                .eq(pageQuery.getSenderId() != null, MsgRecordDO::getSenderId, pageQuery.getSenderId())
                .eq(StringUtils.isNotBlank(pageQuery.getTitle()), MsgRecordDO::getTitle, pageQuery.getTitle())
                .eq(pageQuery.getType() != null, MsgRecordDO::getType, pageQuery.getType())
                .eq(pageQuery.getPriorityLevel() != null, MsgRecordDO::getPriorityLevel, pageQuery.getPriorityLevel())
                .eq(pageQuery.getReadFlag() != null, MsgRecordDO::getReadFlag, pageQuery.getReadFlag())
                .ge(StringUtils.isNotBlank(pageQuery.getSendTimeStart()), MsgRecordDO::getSendTime, pageQuery.getSendTimeStart())
                .le(StringUtils.isNotBlank(pageQuery.getSendTimeEnd()), MsgRecordDO::getSendTime, pageQuery.getSendTimeEnd())
                .orderByDesc(MsgRecordDO::getSendTime,MsgRecordDO::getModifyTime);

        Page<MsgRecordDO> pageDOs = msgRecordMapper.selectPage(new Page<MsgRecordDO>(pageQuery.getPageNum(), pageQuery.getPageSize()), lambdaQueryWrapper);

        List<DictDTO> WikiDictList = Optional.ofNullable(globalClient.queryDictByType(DictTypeEnum.WIKI_TYPE.getValue())).map(ResponseResult::getData).orElse(Collections3.emptyList());
        Map<String, String> WikiDictMap = WikiDictList.parallelStream().collect(Collectors.toMap(DictDTO::getValue, DictDTO::getLabel, (s, a) -> a));

        Page<MsgRecordVO> pageVOs = BeanUtil.convertPage(pageDOs, MsgRecordVO.class);

        if(pageDOs != null && pageDOs.getSize() >0) {
            List<MsgRecordDO> records = pageDOs.getRecords();
            List<MsgRecordVO> recordsResult = new ArrayList<>();
            recordsResult = records.stream().map(c -> {
                MsgRecordVO entityVO = BeanUtil.convertBean(c, MsgRecordVO.class);
                List<MsgRecordAttachDO> MsgRecordAttachDOS = msgRecordAttachMapper.selectList(new LambdaQueryWrapper<MsgRecordAttachDO>()
                        .eq(MsgRecordAttachDO::getMsgId, c.getId())
                );
                if (Collections3.isNotEmpty(MsgRecordAttachDOS)) {
                    List<MsgRecordAttachVO> MsgRecordAttachVOS = JsonUtils.jsonToList(MsgRecordAttachDOS, MsgRecordAttachVO.class);
                    entityVO.setMsgAttachs(MsgRecordAttachVOS);
                }
                entityVO.setPriorityLevelName(PriorityLevelEnum.getNameByLevel(c.getPriorityLevel()));
                entityVO.setReadFlagName(MsgReadStatusEnum.getNameByValue(c.getReadFlag()));
                entityVO.setTypeName(WikiDictMap.get(c.getType().toString()));
                if (c.getSendTime() != null) {
                    entityVO.setSendTimeStr(dateTimeformatter.format(c.getSendTime()));
                }
                if (c.getCreateTime() != null) {
                    entityVO.setCreateTimeStr(dateTimeformatter.format(c.getCreateTime()));
                }

                return entityVO;
            }).collect(Collectors.toList());
            pageVOs.setRecords(recordsResult);
        }
        return pageVOs;
    }

    @Override
    public List<MsgRecordAttachVO> listAttachsByMsgId(Long msgId){
        List<MsgRecordAttachDO> entityAttachDOS = msgRecordAttachMapper.queryAttachByMsgId(msgId);

        if(Collections3.isNotEmpty(entityAttachDOS)){
            return JsonUtils.jsonToList(entityAttachDOS, MsgRecordAttachVO.class);
        }
        return Collections3.emptyList();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(MsgRecordParam param) {
        if(param == null) throw new BusinessException("没有读取到页面数据!");

        checkUnique(param);
        MsgRecordDO entityDO = BeanUtil.convertBean(param, MsgRecordDO.class);
        entityDO.setId(IdGenerator.getId());
        entityDO.setCreateBy(UserUtils.getUserId());
        entityDO.setCreateTime(LocalDateTime.now());
        entityDO.setModifyTime(LocalDateTime.now());
        int insertRows =  msgRecordMapper.insert(entityDO);
        if(insertRows >0){
            Long msgId = entityDO.getId();
            List<MsgRecordAttachDO> tmpentityAttachDOS = msgRecordAttachMapper.queryAttachByMsgId(msgId);
            if(Collections3.isNotEmpty(tmpentityAttachDOS)){
                msgRecordAttachMapper.delteAttachByMsgId(msgId);
            }
            List<MsgRecordAttachParam> MsgRecordAttachParams = param.getMsgAttachs();
            if(Collections3.isNotEmpty(MsgRecordAttachParams)){
                MsgRecordAttachParams.stream().forEach(d->{
                    MsgRecordAttachDO entityAttachDO = BeanUtil.convertBean(d, MsgRecordAttachDO.class);
                    entityAttachDO.setMsgId(msgId);
                    msgRecordAttachMapper.insert(entityAttachDO);
                });
                return true;
            }

            return true;
        }
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modify(MsgRecordParam param){
        if(param == null) throw new BusinessException("没有读取到页面数据!");

        MsgRecordDO entityDO = BeanUtil.convertBean(param, MsgRecordDO.class);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        int updateRows =  msgRecordMapper.updateById(entityDO);
        if(updateRows >0){
            Long msgId = param.getId();
            List<MsgRecordAttachDO> tmpMsgRecordAttachDOS = msgRecordAttachMapper.queryAttachByMsgId(msgId);
            if(Collections3.isNotEmpty(tmpMsgRecordAttachDOS)){
                msgRecordAttachMapper.delteAttachByMsgId(msgId);
            }
            List<MsgRecordAttachParam> entityAttachParams = param.getMsgAttachs();
            if(Collections3.isNotEmpty(entityAttachParams)){
                entityAttachParams.stream().forEach(d->{
                    MsgRecordAttachDO entityAttachDO = BeanUtil.convertBean(d, MsgRecordAttachDO.class);
                    entityAttachDO.setMsgId(msgId);
                    msgRecordAttachMapper.insert(entityAttachDO);
                });
                return true;
            }

            return true;
        }
        return false;
    }

    @Override
    public MsgRecordVO view(Long id){
        MsgRecordDO entityDO = msgRecordMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("记录不存在!");
        MsgRecordVO vo = BeanUtil.convertBean(entityDO, MsgRecordVO.class);

        List<DictDTO> WikiDictList = Optional.ofNullable(globalClient.queryDictByType(DictTypeEnum.WIKI_TYPE.getValue())).map(ResponseResult::getData).orElse(Collections3.emptyList());
        Map<String, String> WikiDictMap = WikiDictList.parallelStream().collect(Collectors.toMap(DictDTO::getValue, DictDTO::getLabel, (s, a) -> a));
        if(vo.getType() != null) {
            vo.setTypeName(WikiDictMap.get(vo.getType().toString()));
        }
        List<MsgRecordAttachDO> entityAttachDOS = msgRecordAttachMapper.queryAttachByMsgId(id);

        if(Collections3.isNotEmpty(entityAttachDOS)) {
            List<MsgRecordAttachVO> entityAttachVOS = JsonUtils.jsonToList(entityAttachDOS, MsgRecordAttachVO.class);
            vo.setMsgAttachs(entityAttachVOS);
        }
        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean changeReadStatus(Long id,Integer readFlag){
        MsgRecordDO entityDO = msgRecordMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("记录不存在!");
        entityDO.setReadFlag(readFlag);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        return msgRecordMapper.updateById(entityDO)>0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean del(Long id){
        MsgRecordDO entityDO = msgRecordMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("记录不存在!");

        return msgRecordMapper.deleteById(id) > 0;
    }

    /**
     * 校验唯一性
     *
     * @param param
     */
    private void checkUnique(MsgRecordParam param) {
        if (param == null) {
            throw new BusinessException("当前数据不存在!");
        }
        //code name确保等级唯一性
        LambdaQueryWrapper<MsgRecordDO> queryWrapper = new LambdaQueryWrapper<MsgRecordDO>()
                .ne(param.getId() != null, MsgRecordDO::getId, param.getId())
                .eq(MsgRecordDO::getTitle, param.getTitle());
        List<MsgRecordDO> dos = msgRecordMapper.selectList(queryWrapper);
        if (Collections3.isNotEmpty(dos)) {
            throw new BusinessException("已经存在同名的数据!");
        }
    }

}
